﻿package component.formula;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import component.formula.exception.FormulaException;
import component.formula.function.AbstractFunction;
import component.formula.function.FunctionLib;
import component.formula.util.CalculateUtil;
import component.formula.util.StringUtil;

public class ExpressionParser {
	
	public static Map funClassMap = FunctionLib.funClassMap;
	
	public static String calculate(String expression) throws FormulaException{
		//首先定位到左括号,如果没有就是简单的四则运算,如果有就计算括号内的(有可能是一个基本的函数)
		if(expression==null || "".equals(expression)){
			throw new FormulaException("表达式为空");
		}
		int leftBracketIndex = expression.indexOf("(");
		if(leftBracketIndex==-1){//简单的四则计算
			expression = expression.trim();
			if(CalculateUtil.isNumberAndPoint(expression)){//数字直接返回
				return expression;
			}else if(CalculateUtil.isBoolean(expression)){//是boolean值也直接返回
				return String.valueOf(CalculateUtil.getBoolean(expression));
			}else if(CalculateUtil.isContainLogic(expression)){//逻辑运算
				AbstractFunction fun = (AbstractFunction)FunctionLib.funClassMap.get("if");
				return String.valueOf(fun.calculate(expression));
			}else if(CalculateUtil.isContainOperator(expression)){//四则运算
				AbstractFunction fun = (AbstractFunction)FunctionLib.funClassMap.get("sum");
				return String.valueOf(fun.calculate(expression));
			}
			return null;
			
		}else if(expression.indexOf(";")!=-1){//多个表达式：if();if();
			String[] expressionArr = expression.split(";");
			for(int i=0;i<expressionArr.length;i++){
				String expressionTemp = expressionArr[i];
				String value = calculate(expressionTemp);//递归计算每个表达式
				if(!"false".equals(value) && !"null".equals(value)){
					return value;
				}
			}
			FormulaException.debug("没有一个条件符合的表达式");
			return "0";
		}else{
			//寻找左右括号的配对
			int leftBrackets = 0;
			int rightBrackets = 0;
			int rightBracketIndex = 0;
			int i=leftBracketIndex;
			for(;i<expression.length();i++){
				char c = expression.charAt(i);
				//System.out.println("c = " + c);
				if(c=='('){
					if(leftBrackets==rightBrackets){
						leftBracketIndex = i;
					}
					leftBrackets++;
				}else if(c==')'){
					rightBrackets++;
					if(leftBrackets==rightBrackets){
						rightBracketIndex = i;
						i = leftBracketIndex;//重新设置寻找括号的起点
						
						//将括号内的表达式用值替换掉
						int lastOper = -1;//必须为-1,如果没有，就从开头算起
						for(int j=leftBracketIndex-1;j>=0;j--){//判断括号前面的是不是基本函数
							char temp = expression.charAt(j);
							if(CalculateUtil.isOperatorOrBracket(temp) || CalculateUtil.isLogic(temp) || temp==' '){
								lastOper = j;
								break;
							}
						}
						String expression2 = expression.substring(leftBracketIndex+1,rightBracketIndex);
						FormulaException.debug("括号内的表达式 = " + expression2);
						String value = expression2;
						String funName = expression.substring(lastOper+1,leftBracketIndex);
						FormulaException.debug("函数名称 = " + funName );
						if(!StringUtil.isNull(funName) && !FunctionLib.isFunction(funName)){
							throw new FormulaException(funName + " 不是函数");
						}
						if(FunctionLib.isFunction(funName)){//是基本函数
							AbstractFunction fun = (AbstractFunction)funClassMap.get(funName);
								
							String paraValues = expression2;
							if(fun.isCal()){
								paraValues = "";
								String[] tempArr = expression2.split(",");
								//计算函数里每个参数的值
								for(int k=0;k<tempArr.length;k++){
									String para = tempArr[k].trim();
									String paraValue = calculate(para);//递归获取参数的值
									paraValues += paraValue + ",";
								}
								paraValues = paraValues.substring(0,paraValues.length()-1);
							}
							FormulaException.debug("函数内的计算值 = " + paraValues);
							
							String value2 = String.valueOf(fun.calculate(paraValues));
							expression = expression.substring(0,lastOper+1)+value2+expression.substring(rightBracketIndex+1);
							FormulaException.debug("运算基本函数后的expression = " + expression);			
						}else{//不是基本函数
							value = calculate(expression2);//递归获取括号内的值
							expression = expression.substring(0,leftBracketIndex)+value+expression.substring(rightBracketIndex+1);
							FormulaException.debug("运算括号内容后的expression = " + expression);	
						}
						
					}
				}
			}
			if(leftBrackets!=rightBrackets){
				throw new FormulaException("左右括号不配对");
			}
			String value = String.valueOf(calculate(expression));
			return value;
		}
	}
	
	public static void main(String[] args) throws FormulaException {
		String exp = "";
		//exp = "1+3+sum(3+45)+47";
		//exp = "(year(2008-07-05)=2005)";
		exp = "(0-1)+3";
		exp = "-1+3";
		exp = "3+(-1)";
		
		exp = "if((1=1 && (2+1)=3),4)";
		exp = "if((1=2 && (2+1)=3),4);if((1=5 && (2+1)=3),3);3+4";//相当于:if(){}else if(){}else{}
		exp = "1000*(year()-year(2005-06-14))";
		
		exp = "formulaValue = if( (300-1600)>0 && (300-1600)<=500 , (300-1600)*5/100);" +
				"if( (300-1600)>500 && (300-1600)<=2000 , (300-1600)*10/100-25);" +
				"if( (300-1600)>2000 && (300-1600)<=5000 , (300-1600)*15/100-125);";
		
		// \r\n
		exp = "if( (2422.00-1600)>0 && (2422.00-1600)<=500 , (2422.00-1600)*5/100);" +
				"if( (2422.00-1600)>500 && (2422.00-1600)<=2000 , (2422.00-1600)*10/100-25);" +
				"if( (2422.00-1600)>2000 && (2422.00-1600)<=5000 , (2422.00-1600)*15/100-125);	";
		
		exp = "if(8a285f7c1aed7341011afc72c080000c=8a285f7c1aed7341011afc72c080000c&&300>300, 300, 500);";
		
		System.out.println(calculate(exp));
	}
}
